# encoding: utf8
import math
import json


def ip_str2num(ip_str: str):  # ip_str to ip_num
    ip = ip_str.split(".")
    ip_num = int(ip[0])*256**3 + int(ip[1])*256**2 + int(ip[2])*256 + int(ip[3])
    return ip_num


def ip_num2str(ip_num: int):      # ip_num to ip_str
    flag = int(ip_num / 256)
    mod = ip_num % 256
    ip = []
    while flag:
        ip.append(str(mod))
        mod = flag % 256
        flag = int(flag / 256)
    ip.append(str(mod))
    return ".".join(ip[::-1])


def load_data(file_name):
    src_fp = open(file_name, "r", encoding="utf8")
    lines = src_fp.readlines()
    src_fp.close()

    result = []
    for each in lines:
        tmp = each.replace("\r", "").replace("\n", "").split("\t")
        tmp[0] = ip_str2num(tmp[0])
        tmp[1] = float(tmp[1])
        tmp[2] = float(tmp[2])
        result.append(tmp[:])

    return result


def min_ip_dist(s_data, ip_str):
    min_dis_ip = ["string", 2 ** 31]
    d_ip_num = ip_str2num(ip_str)
    for each in s_data:
        tmp_dis = abs(ip_str2num(each[0]) - d_ip_num)
        if tmp_dis < min_dis_ip[1]:
            min_dis_ip = [each[0], tmp_dis]

    return min_dis_ip[0]


def min_ipnum_dist(s_data, ip_num):
    min_dis_ip = ["num", 2 ** 31]
    for each in s_data:
        tmp_dis = abs(each[0] - ip_num)
        if tmp_dis < min_dis_ip[1]:
            min_dis_ip = [each[0], tmp_dis]

    return min_dis_ip[0]


def coors_distance(lat1, lng1, lat2, lng2):
    earth_radius = 6378.137
    rad_lat1 = lat1 * math.pi / 180.0
    rad_lat2 = lat2 * math.pi / 180.0
    a = rad_lat1 - rad_lat2
    b = (lng1 * math.pi / 180.0) - (lng2 * math.pi / 180.0)
    s = 2 * math.asin(math.sqrt(math.pow(math.sin(a / 2), 2) + math.cos(rad_lat1) * math.cos(rad_lat2) * math.pow(math.sin(b / 2), 2)))
    s = s * earth_radius
    return s           # km


def net_seg_area(ips, mask):
    result = []
    for ip in ips:
        ip_num = ip_str2num(ip)
        ip_net = ip_num2str(ip_num - (ip_num % (2 ** (32 - mask))))
        if ip_net not in result:
            result.append(ip_net)
    return result


def isInRegion(point, region):
    count = 0
    lon = float(point[0])
    lat = float(point[1])
    for i in range(len(region)):
        # 如果是最后一个元素，那么必然是和第一个一样的，就啥也不干
        if i+1 == len(region):
            break
        # 如果不是最后一个元素，那么需要和后一个元素一起判断给定点是否在区域内
        lo_1, la_1 = region[i]
        lo_2, la_2 = region[i+1]

        la_1, lo_1, la_2, lo_2 = float(la_1), float(lo_1), float(la_2), float(lo_2)

        # 以纬度确定位置，沿纬度向右作射线，看交点个数
        if lat < min(la_1, la_2):
            continue
        if lat > max(la_1, la_2):
            continue
        # 如果和某一个共点那么直接返回true
        if (lat, lon) == (la_1, lo_1) or (lat, lon) == (la_2, lo_2):
            return True
        # 如果和两点共线
        if lat == la_1 == la_2:
            if lon < min(lo_1, lo_2) or lon > max(lo_1, lo_2):
                return False
            else:
                return True
        # 接下来只需考虑射线穿越的情况，该情况下的特殊情况是射线穿越顶点
        # 求交点的精度
        cross_lon = (lat - la_1) * (lo_2 - lo_1) / (la_2 - la_1) + lo_1
        # 因为需要考虑特殊情况的射线穿越顶点，因此只判断是不是穿越左边这个顶点
        if cross_lon == la_1:
            count += 1
        # 其他情况
        elif cross_lon > lon:
            count += 1
    if count%2 == 0:
        return False
    return True


def in_city(point, city_name):
    lng = float(point[0])
    lat = float(point[1])
    area_file = "area/" + str(city_name) + ".json"
    a_fp = open(area_file, "r", encoding="utf8")
    info = json.loads(a_fp.readline())
    a_fp.close()
    coors = info["features"][0]["geometry"]["coordinates"]

    flag = False

    for each_coors in coors:
        all_coors = each_coors[0]
        flag = isInRegion([lng, lat], all_coors)
        if flag:
            break
    if flag:
        return True
    else:
        return False

